package com.fdb.efp.nls.service.impl;

import com.fdb.basic.framework.core.base.FrameworkService;
import com.fdb.basic.framework.core.constant.MonAlrmLvlEnums;
import com.fdb.basic.framework.core.util.*;
import com.fdb.efp.nls.service.domain.TxtFileLoadBean;
import com.fdb.efp.nls.service.domain.dw.ListHitDateBean;
import com.fdb.efp.nls.service.facade.ListFileAnalysisService;
import com.fdb.efp.cus.service.facade.CusAccoutErroTempService;
import com.fdb.efp.cus.service.facade.CusHitCaseInfoService;
import com.fdb.efp.cus.service.vo.AccoutErroTempVO;
import com.fdb.efp.cus.service.vo.CusHitCaseInfoVO;
import com.fdb.efp.nls.service.facade.AccLoanService;
import com.fdb.efp.nls.service.vo.AccLoanVO;
import com.fdb.efp.report.service.facade.RptHitCusInfoService;
import com.fdb.efp.report.service.vo.RptHitCusInfoVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.fdb.efp.nls.service.util.TxtFileLoadPluginBatch;


import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;


/**
 *
 * 名单系统命中案例文件解析接口
 *
 * @author dengqiwen
 * @since 2020年03月11日
 * @version 1.0
 */
@Service("listFileAnalysisService")
public class ListFileAnalysisServiceImpl implements ListFileAnalysisService, FrameworkService {


    private static Logger logger = LoggerFactory.getLogger(ListFileAnalysisServiceImpl.class);

    // 名单系统命中案例文件下载到本地的路径
    @Value("${analysis.listHitFilePath}")
    private String listHitFilePath;

    // 对外SFTP文件服务器：下载地址
    @Value("${analysis.remoteDownListFilePath}")
    private String remoteDownListFilePath;

    // 对外SFTP文件服务器IP地址
    @Value("${analysis.outFtpHost}")
    private String outFtpHost;

    // 对外SFTP文件服务器用户名
    @Value("${analysis.outUserName}")
    private String outUserName;

    // 对外SFTP文件服务器登录密码
    @Value("${analysis.outPassword}")
    private String outPassword;

    // 对外SFTP文件服务器端口号
    @Value("${analysis.outFtpPort}")
    private int outFtpPort;

    // 名单系统命中案例文件名称
    @Value("${analysis.listHitFileName}")
    private String listHitFileName;

    // 分割符
    @Value("${analysis.dataTransferFileSeparation}")
    private String dataTransferFileSeparation;

    // 同步文件记录异常信息
    @Autowired
    @Qualifier("cusAccoutErroTempService")
    private CusAccoutErroTempService accoutErroTempService;

    @Autowired
    @Qualifier("cusHitCaseInfoService")
    private CusHitCaseInfoService cusHitCaseInfoService;

    @Autowired
    @Qualifier("accLoanService")
    private AccLoanService accLoanService;
    @Autowired
    @Qualifier("rptHitCusInfoService")
    private RptHitCusInfoService rptHitCusInfoService;

    /**
     *
     * 名单系统命中案例文件下载解析
     * 	 * @author dengqiwen
     * 	 * @since 2020年3月15日
     * 	 * @version 0.1
     */
    @Override
    public boolean analysisFile(String curDate) throws Exception {
        // 对外SFTP文件服务器下载文件
        boolean result = true;
        String listFilePath="";
        logger.info("名单系统命中案例文件下载并解析加工数据开始，文件路径：" + listHitFilePath);
        try {
            String newListHitFileName = listHitFileName.trim().replaceAll("curDate", curDate);
            //从sftp服务器下载文件到本地
            boolean fileDownRes = downloadFile(newListHitFileName);
            // 解析文件
            listFilePath=listHitFilePath+newListHitFileName;
            File tranFile = new File(listFilePath);
            // 如果文件存在，则落表
            if (fileDownRes && tranFile.exists()) {
                TxtFileLoadPluginBatch txtFileLoadPlugin = new TxtFileLoadPluginBatch(listFilePath, dataTransferFileSeparation, "UTF-8", 0, 1000);
                List<TxtFileLoadBean> txtFileLoadList = txtFileLoadPlugin.run(new ListHitDateBean());
                //同步名单系统命中案例数据，落cus_hit_case_info表
                result=synchDate(txtFileLoadList,curDate);
                if (txtFileLoadList.size() != 0) {
                    while (!txtFileLoadList.get(txtFileLoadList.size() - 1).isReadedComplete) {
                        txtFileLoadPlugin.setFirstRead(false);
                        txtFileLoadList = txtFileLoadPlugin.run(new ListHitDateBean());
                        if (txtFileLoadList.size() == 0) {
                            break;
                        }
                        result=synchDate(txtFileLoadList,curDate);
                    }
                }
            }

            logger.info("名单系统命中案例文件下载并解析加工数据结束：" + result);
        } catch (Exception e) {
            e.printStackTrace();
            String errorMsg = "名单系统命中案例文件下载并解析加工数据异常";
            String remark = "名单系统命中案例文件下载并解析加工数据异常，异常信息：" + e.getMessage();
            String tableName = "cus_hit_case_info";
            logger.error(remark);
            if(remark.length()>950){
                remark=remark.substring(0,950);
            }
            addErrorInfo(tableName, MonAlrmLvlEnums.MonAlrmLvlEnum.SERIOUS.getEnname(), errorMsg, remark);
            result=false;
        }
        logger.info("名单系统命中案例文件下载并解析加工数据结束，解析文件：" + listFilePath);
        return result;
    }


    /**
     *
     * 名单系统命中案例数据回溯报表
     * @author dengqiwen
     * @since 2020年3月15日
     * @version 0.1
     */
    @Override
    public boolean hitCusCaseInfo(){
        boolean result = false;
        logger.info("名单系统命中案例数据回溯报表开始");
        try {
            //不管名单系统是否有数据传过来，都去cus_hit_case_info查出所有有证件号码的数据,去找出今天有没有命中网贷的用户-因为每天都有新增用户
            List<CusHitCaseInfoVO> cusHitCaseInfoList = cusHitCaseInfoService.queryAll();
            //取出证件号码、证件类型
            List<String> certTypes = cusHitCaseInfoList.stream().map(CusHitCaseInfoVO::getCertType).collect(Collectors.toList());
            List<String> certCodes = cusHitCaseInfoList.stream().map(CusHitCaseInfoVO::getCertCode).collect(Collectors.toList());
            List<AccLoanVO> accloanList = new ArrayList<>();
            if (Objects.nonNull(certCodes) && !certCodes.isEmpty()) {
                //拿证件号码、证件类型去acc_loan表查出0,1,10，14状态即在贷/通过审批未放款的借据
                accloanList = accLoanService.batchQuerybyCert(certTypes, certCodes);
            }
            result = disposeData(accloanList, cusHitCaseInfoList);
            logger.info("名单系统命中案例数据回溯报表结束");
        }catch (Exception e){
            e.printStackTrace();
            String errorMsg = "名单系统命中案例数据回溯报表异常";
            String remark = "名单系统命中案例数据回溯报表异常，异常信息：" + e.getMessage();
            logger.error(remark);
            String tableName = "rpt_hit_cus_info";
            if(remark.length()>950){
                remark=remark.substring(0,950);
            }
            addErrorInfo(tableName, MonAlrmLvlEnums.MonAlrmLvlEnum.SERIOUS.getEnname(), errorMsg, remark);
            result=false;

        }
        return result;
    }




    /**
     *
     * 从对外SFTP文件服务器下载名单系统命中案例文件 <br>
     * 0.1:ludayong:2019年5月20日 下午3:59:51:新增 <br>
     *
     * @author ludayong
     * @since 2019年5月20日 下午3:59:51
     * @date 2019年5月20日 下午3:59:51
     * @version 0.1
     */
    private boolean downloadFile(String newListHitFileName) throws Exception {
        // 连接对外SFTP文件服务器
        SFTPUtil sftpUtil = null;
        // 下载文件是否成功
        boolean result = false;
        try {
            // 从对外SFTP文件服务器下载文件到本地
            logger.info("对外SFTP文件服务器信息：" + outUserName + " / " + outPassword + " IP: " + outFtpHost + " 端口号：" + outFtpPort);
            sftpUtil = new SFTPUtil(outUserName, outPassword, outFtpHost, outFtpPort);
            logger.info("对外SFTP文件服务器下载名单系统命中案例地址：" + remoteDownListFilePath+newListHitFileName);
            logger.info("下载名单系统命中案例文件到本地的地址：" + listHitFilePath+newListHitFileName);
            // 下载文件
            result = sftpUtil.downFile(sftpUtil, remoteDownListFilePath, newListHitFileName, listHitFilePath,
                    newListHitFileName, false);
            logger.info("对外SFTP文件服务器下载名单系统命中案例文件：" + remoteDownListFilePath + newListHitFileName + "，结果[" + result + "]");
        } catch (Exception e) {
            e.printStackTrace();
            String remark = "对外SFTP服务器下载文件出现异常，异常信息：" + e.getMessage();
            logger.error(remark);
            throw new Exception(remark);
        } finally {
            if (sftpUtil != null) {
                sftpUtil.closeSFTP();
            }
        }
        return result;
    }



    public boolean synchDate(List<TxtFileLoadBean> txtFileLoadList,String curDate) throws Exception{
        logger.info("同步名单系统案例文件开始-落cus_hit_case_info表开始！");
        // 同步数据进 名单系统命中案例数据表
        List<CusHitCaseInfoVO> cusHitCaseInfoList= new ArrayList<CusHitCaseInfoVO>();
        // 处理结果
        boolean result = false;
        // 新增或者修改的额度信息数量
        int cusHitCaseInfoNum = 0;
        try {
            for (int i = 0; i < txtFileLoadList.size(); i++) {
                ListHitDateBean listHitDateBean = (ListHitDateBean) txtFileLoadList.get(i);
                // 需要新增或者更新的案例信息
                CusHitCaseInfoVO cusHitCaseInfoVO = initCusHitCaseInfo(listHitDateBean,curDate);
                if (Objects.nonNull(cusHitCaseInfoVO)) {
                    cusHitCaseInfoList.add(cusHitCaseInfoVO);
                }
            }
            if (Objects.nonNull(cusHitCaseInfoList) && !cusHitCaseInfoList.isEmpty()) {
                List<CusHitCaseInfoVO> addList=cusHitCaseInfoList.stream().filter(CusHitCaseInfoVO->CusHitCaseInfoVO.getStatus().equals("A")).collect(Collectors.toList());
                List<CusHitCaseInfoVO> updateList=cusHitCaseInfoList.stream().filter(CusHitCaseInfoVO->CusHitCaseInfoVO.getStatus().equals("U")).collect(Collectors.toList());
                List<CusHitCaseInfoVO> deleteList=cusHitCaseInfoList.stream().filter(CusHitCaseInfoVO->CusHitCaseInfoVO.getStatus().equals("D")).collect(Collectors.toList());
                //重复跑批的情况下，后面的记录覆盖前面的记录
                if (Objects.nonNull(addList) && !addList.isEmpty()) {
                    for (CusHitCaseInfoVO cus:addList){
                        cus.setStatus("0");
                        //插入之前先去查有没有值，如果有值就更新，没值就插入（因为有可能重复跑批）
                        CusHitCaseInfoVO cusHitCaseInfoVO = cusHitCaseInfoService.queryByPart(cus);
                        if(Objects.nonNull(cusHitCaseInfoVO)){
                            cusHitCaseInfoService.updateCusHitCaseInfo(cus);
                        }else{
                            cusHitCaseInfoService.insertCusHitCaseInfo(cus);
                        }
                    }
                }
                if (Objects.nonNull(updateList) && !updateList.isEmpty()) {
                    for (CusHitCaseInfoVO cus:updateList){
                        cus.setStatus("0");
                        //更新之前先去查有没有值，如果有值就更新，没值就插入（因为应测试要求：有可能之前没有成功插入的情况）
                            CusHitCaseInfoVO cusHitCaseInfoVO2 = cusHitCaseInfoService.queryByPart(cus);
                            if(Objects.nonNull(cusHitCaseInfoVO2)){
                                cusHitCaseInfoService.updateCusHitCaseInfo(cus);
                            }else{
                                cusHitCaseInfoService.insertCusHitCaseInfo(cus);
                            }

                    }
                }
                if (Objects.nonNull(deleteList) && !deleteList.isEmpty()) {
                    for (CusHitCaseInfoVO cus:deleteList){
                        cus.setStatus("1");
                        //更新之前先去查有没有值，如果有值就更新，没值就插入（因为应测试要求：有可能之前没有成功插入的情况）
                            CusHitCaseInfoVO cusHitCaseInfoVO2 = cusHitCaseInfoService.queryByPart(cus);
                            if(Objects.nonNull(cusHitCaseInfoVO2)){
                                cusHitCaseInfoService.updateCusHitCaseInfo(cus);
                            }else{
                                cusHitCaseInfoService.insertCusHitCaseInfo(cus);
                            }
                    }

                }
            }
            result = true;
        }catch (Exception e) {
            e.printStackTrace();
            String remark="同步名单系统案例文件-落cus_hit_case_info表出错"+e.getMessage();
            logger.error(remark);
            result = false;
            throw new Exception(remark);
        }finally {
            txtFileLoadList=null;
            cusHitCaseInfoList=null;
            logger.info("同步名单系统案例文件-落cus_hit_case_info表结束！");
        }
        return result;
    }



    /**
     *
     * 初始化名单系统命中案例数据表
     *
     * @author dengqiwen
     * @date 2020年3月17日
     * @version 0.1
     */
    public CusHitCaseInfoVO initCusHitCaseInfo(ListHitDateBean listHitDateBean,String curDate) {
        CusHitCaseInfoVO cus =null;
        if(StringUtil.isNotEmpty(listHitDateBean.getCertCode()) || StringUtil.isNotEmpty(listHitDateBean.getTradeAccount())){
            cus=new CusHitCaseInfoVO();
            cus.setCusId(listHitDateBean.getCusId());
            cus.setCertType(listHitDateBean.getCertType());
            cus.setCertCode(listHitDateBean.getCertCode());
            cus.setCusName(listHitDateBean.getCusname());
            cus.setTradeBank(listHitDateBean.getTradebank());
            cus.setTradeAccount(listHitDateBean.getTradeAccount());
            cus.setTradeName(listHitDateBean.getTradeName());
            cus.setStatus(listHitDateBean.getStatus());
            cus.setHitType(listHitDateBean.getHitType());
            cus.setFileTime(listHitDateBean.getHitType());
            cus.setFileTime(DateUtility.format8To10(curDate));
        }
        return cus;
    }

    public boolean disposeData(List<AccLoanVO> accloanList,List<CusHitCaseInfoVO> cusHitCaseInfoList) throws Exception{
        boolean result = true;
        if (Objects.nonNull(accloanList) && !accloanList.isEmpty() && Objects.nonNull(cusHitCaseInfoList) && !cusHitCaseInfoList.isEmpty()) {
            List<RptHitCusInfoVO> rptInfoList =new ArrayList<RptHitCusInfoVO>();
            logger.info("同步名单系统案例文件开始-落rpt_hit_cus_info表开始！");
            int num=0;
            try {
                //同一个用户可能有好几笔贷款
                for(AccLoanVO accloan :accloanList){
                    for(CusHitCaseInfoVO cus :cusHitCaseInfoList){
                        if(accloan.getCertCode().equals(cus.getCertCode())){
                            //提示类名单不展示
                            if(!cus.getHitType().equals("PRMT")){
                                RptHitCusInfoVO rptInfo=new RptHitCusInfoVO();
                                rptInfo.setCusName(accloan.getCusName());
                                rptInfo.setCertType(accloan.getCertType());
                                rptInfo.setCertCode(accloan.getCertCode());
                                rptInfo.setApplyDate(accloan.getLoanStartDate());
                                rptInfo.setApplyNo(accloan.getBillNo());
                                if(cus.getHitType().equals("SAN")){
                                    rptInfo.setHitType("禁止类名单");
                                }else if(cus.getHitType().equals("LMT")){
                                    rptInfo.setHitType("限制类名单");
                                }
                                rptInfo.setLoanBalance(accloan.getLoanBalance());
                                rptInfo.setLoanMoney(accloan.getLoanAmount());
                                rptInfo.setLoanTerm(accloan.getLoanTerm());
                                rptInfo.setPrdCode(accloan.getPrdCode());
                                rptInfo.setPrdName(accloan.getPrdName());
                                rptInfo.setFileTime(cus.getFileTime());
                                rptInfo.setStatus(cus.getStatus());
                                rptInfoList.add(rptInfo);
                            }

                        }
                    }
                }
                if (Objects.nonNull(rptInfoList) && !rptInfoList.isEmpty()) {
                    num=rptHitCusInfoService.insertOrUpdateBatch(rptInfoList);
                }

            }catch (Exception e){
                e.printStackTrace();
                String remark="同步名单系统案例文件-落rpt_hit_cus_info出错"+e.getMessage();
                logger.error(remark);
                result = false;
                throw new Exception(remark);
            }
            logger.info("同步名单系统案例文件-落rpt_hit_cus_info结果:"+num);
        }
        return result;
    }


    /**
     *
     * 名单系统命中案例文件清理 <br>
     * @author dengqiwen
     * @date 2020年04月02日
     * @version 0.1
     */
    public boolean clearListFile(String curDate) {
        boolean result = false;
        try {
            String newListHitFileName = listHitFileName.trim().replaceAll("curDate", curDate);
            // 解析文件
            String filePath=listHitFilePath+newListHitFileName;
            logger.info("名单系统命中案例文件清理路径：" + filePath);
            // 账务文件路径
            File files = new File(filePath);
            // 同步文件解析路径
            if (files.exists()) {
                if (files.isFile()) {
                    boolean removeFileRes = ZipUtil.deleteFile(files.getAbsolutePath());
                    logger.info("名单系统命中案例文件清理:" + files.getAbsolutePath() + "结果[" + removeFileRes + "]");
                }
            }
            result = true;
        } catch (Exception e) {
            result = false;
            String errorMsg = "名单系统命中案例文件清理异常！";
            String remark = "名单系统命中案例文件清理，错误信息：" + e.getMessage();
            logger.error(remark);
            String tableName = "cus_hit_case_info";
            if(remark.length()>950){
                remark=remark.substring(0,950);
            }
            addErrorInfo(tableName, MonAlrmLvlEnums.MonAlrmLvlEnum.SERIOUS.getEnname(), errorMsg, remark);

        }
        return result;
    }

    /**
     *
     * 记录异常信息 <br>
     * 0.1:ludayong:2019年5月7日 上午11:31:23:新增 <br>
     *
     * @author ludayong
     * @since 2019年5月7日 上午11:31:23
     * @date 2019年5月7日 上午11:31:23
     * @version 0.1
     */
    private void addErrorInfo(String tableName, String errorType, String errorMsg, String remark) {
        AccoutErroTempVO accoutErroTempVO = new AccoutErroTempVO();
        // 表名
        accoutErroTempVO.setTableName(tableName);
        // 错误级别
        accoutErroTempVO.setErroType(errorType);
        // 错误信息
        accoutErroTempVO.setErroMsg(errorMsg);
        // 备注
        accoutErroTempVO.setRemark(remark);
        // 创建时间
        accoutErroTempVO.setCreateData(DateTool.getCurrentDateTime());
        // 修改时间
        accoutErroTempVO.setLastModifyTime(DateTool.getCurrentDateTime());
        // 记录异常信息
        accoutErroTempService.insert(accoutErroTempVO);
    }




}
